﻿using System.Collections.Generic;
using UnityEngine;

public abstract class Player : MonoBehaviour,PlayerContext, ItemTriggerReceiver,Damageable
{

    public class ScenarioAction
{
    private Dictionary<string, float> floatDict = new();
    private Dictionary<string, bool> boolDict = new();
    public float GetFloat(string key, float defaultValue)
    {
        return floatDict.GetValueOrDefault(key, defaultValue);
    }
    public bool GetBool(string key, bool defaultValue)
    {
        return boolDict.GetValueOrDefault(key, defaultValue);
    }

    public void SetFloat(string key, float value)
    {
        if (floatDict.ContainsKey(key))
        {
            floatDict[key] = value;
        }
        else
        {
            floatDict.Add(key, value);
        }
    }
    public void SetBool(string key, bool value)
    {
        if (boolDict.ContainsKey(key))
        {
            boolDict[key] = value;
        }
        else
        {
            boolDict.Add(key, value);
        }
    }
    public bool RemoveFloat(string key)
    {
        if (floatDict.ContainsKey(key))
        {
            return floatDict.Remove(key);
        }
        else
        {
            return false;
        }

    }

    public bool RemoveBool(string key)
    {
        if (boolDict.ContainsKey(key))
        {
            return boolDict.Remove(key);
        }
        else
        {
            return false;
        }
    }

    public bool ContainsKey(string key)
    {
        return floatDict.ContainsKey(key) || boolDict.ContainsKey(key);
    }
}

    public enum KeyMapKey
    {
        Horizontal = 1,
        Vertical,
        Fire,
        Jump,
    }

    public enum Scenario
    {
        None = 0,
        Scene1Finished,
        Scene2Finished,
    }

    /**
     * <summary>
     * 
     * </summary>
     * <param name="context">Player对象</param>
     * <returns>场景动作是否结束</returns>
     */
    public delegate ScenarioAction ScenarioDelegate(PlayerContext context);


    [System.Serializable]
    public class BulletSet
    {
        public ABullet.BulletType bulletType;
        public GameObject bulletPrefabs;
    }

    [Header("基础配置")]
    [Tooltip("跟随角色的摄像机")]
    public Camera followCamera;
    protected CameraLevel cameraLevel;
    protected Camera3DLevel camera3DLevel;

    [Tooltip("角色状态")]
    protected PlayerContext.EnumState playerState;

    [Tooltip("按键方向")]
    protected Vector2 keyDir;
    [Tooltip("角色面向的方向")]
    protected Vector2 lookAt;

    [Header("子弹配置")]
    [Tooltip("当前使用的子弹")]
    public ABullet.BulletType bulletType = ABullet.BulletType.C;
    [Tooltip("子弹类型对应的子弹预制件")]
    protected readonly Dictionary<ABullet.BulletType, GameObject> dictBulletType = new();
    [Tooltip("是否获得R枪")]
    protected bool bulletR = false;

    [Tooltip("当前是否触达地面")]
    protected bool onGround = false;

    public abstract PlayerContext.EnumPlayer PlayerIdentity { get; set;}

    public abstract int GetLife();

    // public abstract void RunScenario(Scenario scenario);
    public abstract void RunScenario(ScenarioDelegate scenarioDelegate);
    public abstract Vector2 GetBodyPartPosition(Person.BodyPart bodyPart);

    public CameraLevel.LevelType CameraLevelType
    {
        get
        {
            if (followCamera.TryGetComponent(out CameraLevel cameraLevel))
            {
                return cameraLevel.levelType;
            }
            else
            {
                return CameraLevel.LevelType.Normal;
            }
        }
    }


    public bool Is3DLevel()
    {
        return cameraLevel.Is3DLevel();
    }
    public bool Is3DBossLevel()
    {
        return cameraLevel.Is3DBossLevel();
    }

    public abstract void BodyPartCollision(GameObject targetGameObject);

    public void OnTriggerEnter2D(Collider2D collision)
    {
        BodyPartCollision(collision.gameObject);

    }

    public void OnTriggerExit2D(Collider2D collision)
    {
        BodyPartCollision(collision.gameObject);

    }

    public void OnTriggerStay2D(Collider2D collision)
    {
        BodyPartCollision(collision.gameObject);

    }

    public void OnCollisionEnter2D(Collision2D collision)
    {
        BodyPartCollision(collision.gameObject);

    }

    public void OnCollisionExit2D(Collision2D collision)
    {
        BodyPartCollision(collision.gameObject);

    }

    public void OnCollisionStay2D(Collision2D collision)
    {
        BodyPartCollision(collision.gameObject);

    }

    public float Damage(GameObject source, float value)
    {
        this.BodyPartCollision(source);
        return value;
    }
    
    public PlayerContext.EnumState GetPlayerState(){
        return playerState;
    }
    public Vector2 GetLookAt(){
        return this.lookAt;
    }
    public Vector2 GetKeyDirection(){
        return this.keyDir;
    }

    public abstract Vector2 UpperBodyOffset();
    public abstract Vector2 LowerBodyOffset();
    public abstract Vector2 RollBodyOffset();
    public abstract Vector2 FallBodyOffset();
    public abstract Vector2 ProstrateBodyOffset();
    public abstract Vector2 InWaterBodyOffset();
    public abstract Vector2 RippleBodyOffset();
    public abstract Vector2 DiedBodyOffset();
    public abstract Vector2 ForwardBodyOffset();
    public abstract Vector2 ForwardProstrateBodyOffset();
    public abstract Vector2 ElectricShockBodyOffset();
    public abstract Vector2 GoAheadBodyOffset();    

    public abstract Vector2 UpperBodyPosition();
    public abstract Vector2 LowerBodyPosition();
    public abstract Vector2 RollBodyPosition();
    public abstract Vector2 FallBodyPosition();
    public abstract Vector2 ProstrateBodyPosition();
    public abstract Vector2 InWaterBodyPosition();
    public abstract Vector2 RippleBodyPosition();
    public abstract Vector2 DiedBodyPosition();
    public abstract Vector2 ForwardBodyPosition();
    public abstract Vector2 ForwardProstrateBodyPosition();
    public abstract Vector2 ElectricShockBodyPosition();
    public abstract Vector2 GoAheadBodyPosition();      

    public CameraLevel GetLevel(){
        return cameraLevel;
    }
    public Camera3DLevel Get3DLevel(){
        return camera3DLevel;
    }
    public ABullet.BulletType GetBulletType(){
        return bulletType;
    }

    public bool IsOnGround(){
        return onGround;
    }

    public Vector2 LookAt { 
        get{
            return this.lookAt;
        } 
        set {
            this.lookAt=value;
        }
    }
    public Vector2 KeyDirection { 
        get{
            return this.keyDir;
        } 
    }
    public Vector3 Position { 
        get{
            return transform.position;
        } 
        set{
            transform.position=value;
        }
    }
}
